﻿using System;
using System.Linq;
using CkSoftware.GroupMe.Sdk.Core.Dao;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace CkSoftware.GroupMe.Sdk.Core.Serialization
{
	/// <summary>
	/// <see cref="JsonConverter" /> for <see cref="GroupMeAttachmentBase" />.
	/// </summary>
	public class GroupMeAttachmentConverter : JsonConverter
	{
		/// <summary>
		/// Determines whether this instance can convert the specified object type.
		/// </summary>
		/// <param name="objectType">Type of the object.</param>
		/// <returns>
		/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
		/// </returns>
		public override bool CanConvert(Type objectType)
		{
			return objectType == typeof (GroupMeAttachmentBase);
		}

		/// <summary>
		/// Reads the JSON representation of the object.
		/// </summary>
		/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader" /> to read from.</param>
		/// <param name="objectType">Type of the object.</param>
		/// <param name="existingValue">The existing value of object being read.</param>
		/// <param name="serializer">The calling serializer.</param>
		/// <returns>
		/// The object value.
		/// </returns>
		public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
		{
			if (reader.TokenType == JsonToken.StartArray)
			{
				JArray dataArray = JArray.Load(reader);
				return dataArray
					.Select(item => ProcessItem(item, serializer))
					.Where(processedData => processedData != null)
					.ToList();
			}

			JObject data = JObject.Load(reader);
			return ProcessItem(data, serializer);
		}

		/// <summary>
		/// Writes the JSON representation of the object.
		/// </summary>
		/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter" /> to write to.</param>
		/// <param name="value">The value.</param>
		/// <param name="serializer">The calling serializer.</param>
		public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
		{
			serializer.Serialize(writer, value);
		}

		private static GroupMeAttachmentBase ProcessItem(JToken data, JsonSerializer serializer)
		{
			string attachmentType = data["type"].ToString().ToUpperInvariant();

			switch (attachmentType)
			{
				case "IMAGE":
					return serializer.Deserialize<GroupMeImageAttachment>(data.CreateReader());
				case "LOCATION":
					return serializer.Deserialize<GroupMeLocationAttachment>(data.CreateReader());
				case "EMOJI":
					return serializer.Deserialize<GroupMeEmojiAttachment>(data.CreateReader());
			}

			return null;
		}
	}
}